//
//  PEBleCmd.m
//  RuiHeAppApp
//
//  Created by Yan Chen on 2024/3/28.
//

#import "RHBleCmdData.h"
#import "JCDataConvert.h"

@implementation RHBleCmdData
#pragma mark ------ 根据 字段 组装读取指令 --------

+(NSData*)buildSingleReadCmdWithEndpointType:(CmdEnpointType)type regAddr:(int)addr byteLength:(int)lengh
{
    return [self buildMultipleReadCmdWithEndpointType:type count:lengh regAddr:addr];
}

//根据字段读取多个寄存器值 
+(NSData*)buildMultipleReadCmdWithEndpointType:(CmdEnpointType)type count:(NSInteger)count regAddr:(int)addr
{
   
    NSMutableData *sendData = [NSMutableData data];
    //------------报文头-------------
    //起始地址(事务处理标识符)
    NSData *addressData = [JCDataConvert intToDataOfTwoByte:addr];
    [sendData appendData:addressData];
    
    //协议标识符
    Byte identify[2] = {0x00,0x00};
    NSData *idData = [NSData dataWithBytes:identify length:sizeof(identify)];
    [sendData appendData:idData];
    
    //长度(从本字节下一个到最后)
    NSData *data_l = [JCDataConvert intToDataOfTwoByte:9];;
    [sendData appendData:data_l];
    
    //读取的端点类型(EMS,Master)
    NSData *typeData = [JCDataConvert intToData:(int)type];
    [sendData appendData:typeData];
    
    //------------------------
    //读取的端点类型(EMS,Master)
    NSData *typeData2 = [JCDataConvert intToData:(int)type];
    [sendData appendData:typeData2];
    
    //指令类型(读取多个)
    NSData *funData = [JCDataConvert intToData:0x03];
    [sendData appendData:funData];
    
    //读取的寄存器起始地址
    [sendData appendData:addressData];
    
    //读取字节长度
    NSData *lengData = [JCDataConvert intToDataOfTwoByte:count];
    [sendData appendData:lengData];
    
    //校验码
    Byte  data_bytes[sendData.length];
    [sendData getBytes:data_bytes length:sendData.length];
    
    int crc_code = [self CRC_16_MODBUS:data_bytes leng:sendData.length];
    NSData *crcData = [JCDataConvert intToDataOfTwoByte:crc_code];
    [sendData appendData:crcData];
    NSLog(@" ----->根据字段读取%ld个寄存器信息 ,起始地址:%d",count,[JCDataConvert dataToInt:addressData]);
    return sendData;
}

#pragma mark ------ 根据 参数模型 读取 单个 寄器值 --------
+(NSData*)buildSingleReadCmdWithSettingModel:(RHLocalSettingModel*)settingModel settingType:(LocalSettingType)type
{
    return [self buildMultipleReadCmdWithSettingModel:settingModel settingType:type];
}

///根据 模型 读取 多个 寄器值
+(NSData*)buildMultipleReadCmdWithSettingModel:(RHLocalSettingModel*)settingModel settingType:(LocalSettingType)type
{
    
    NSMutableData *sendData = [NSMutableData data];
    //------------ 报文头 -------------
    //起始地址(事务处理标识符)
    NSData *addressData = [JCDataConvert intToDataOfTwoByte:settingModel.regAddr];
   
    [sendData appendData:addressData];
    
    //协议标识符
    Byte identify[2] = {0x00,0x00};
    NSData *idData = [NSData dataWithBytes:identify length:sizeof(identify)];
    [sendData appendData:idData];
    
    //长度(从本字节下一个到最后)
    NSData *data_l = [JCDataConvert intToDataOfTwoByte:9];;
    [sendData appendData:data_l];
    
    //读取的端点类型(EMS,Master)
    CmdEnpointType cmdType = [self toCmdType:type];
    if(settingModel.cmdType){
        cmdType = [self toCmdType:[settingModel.cmdType integerValue]];
    }
    NSData *typeData = [JCDataConvert intToData:(int)cmdType];
    [sendData appendData:typeData];
    
    //------------------------
    //读取的端点类型(EMS,Master)
    CmdEnpointType cmdType2 = cmdType;
    NSData *typeData2 = [JCDataConvert intToData:(int)cmdType2];
    [sendData appendData:typeData2];
    
    //指令类型(读)
    NSData *funData = [JCDataConvert intToData:0x03];
    [sendData appendData:funData];
    
    //读取的寄存器起始地址
    [sendData appendData:addressData];
    
    //读取字节长度 (需不需要根据位宽算,不足一个寄存器(16位)的按一个读取)
    int byteLeng = settingModel.bitWidth / 16;
    //如果设置了连续读取多个,如时间校准,电芯数据等
    if(settingModel.readAddrCount >1){
        byteLeng = settingModel.readAddrCount;
    }
    NSData *lengData = [JCDataConvert intToDataOfTwoByte:byteLeng == 0?1:byteLeng];
    [sendData appendData:lengData];
    
    //校验码
    Byte  data_bytes[sendData.length];
    [sendData getBytes:data_bytes length:sendData.length];
    
    int crc_code = [self CRC_16_MODBUS:data_bytes leng:sendData.length];
    NSData *crcData = [JCDataConvert intToDataOfTwoByte:crc_code];
    [sendData appendData:crcData];
    NSLog(@" ----->根据模型 读取信息 key:%@ 寄存器地址:%ld  位宽:%ld 偏移量:%ld",settingModel.field,settingModel.regAddr,settingModel.bitWidth,settingModel.offset);
    return sendData;
}


#pragma mark ------ 根据 字段 组装设置指令 --------
+(NSData*)buildSingleSetCmdWithEndpointType:(CmdEnpointType)type paraKey:(NSString*)key value:(int)value
{
    NSLog(@" ----->设置%@信息",key);
    NSMutableData *sendData = [NSMutableData data];
    //端点类型
    NSData *typeData = [JCDataConvert intToData:(int)type];
    [sendData appendData:typeData];
    
    //指令类型
    NSData *funData = [JCDataConvert intToData:0x06];
    [sendData appendData:funData];
    
    //起始地址
    NSData *addressData = [JCDataConvert regAdressWithParaKey:key];
    [sendData appendData:addressData];
    
    //设置值
    NSData *setData = [JCDataConvert intToDataOfTwoByte:value];
    [sendData appendData:setData];
    
    //校验码
    Byte  data_bytes[sendData.length];
    [sendData getBytes:data_bytes length:sendData.length];
    
    int crc_code = [self CRC_16_MODBUS:data_bytes leng:sendData.length];
    NSData *crcData = [JCDataConvert intToDataOfTwoByte:crc_code];
    [sendData appendData:crcData];
    return sendData;
}

///根据 模型 设置单个寄器值
+(NSData*)buildSingleSetCmdWithSettingModel:(RHLocalSettingModel*)settingModel settingType:(LocalSettingType)type
{
    NSLog(@" ----->设置%@信息 寄存器地址:%ld  位宽:%ld 偏移量:%ld",settingModel.field,settingModel.regAddr,settingModel.bitWidth,settingModel.offset);
    NSMutableData *sendData = [NSMutableData data];
    //-----------如果是配网指令,为了兼容以前的版,配网指令不走modbus,全部用字符串发送
    if (type == LocalSettingType_NetWorkConfig) {
        NSData *keyData     = [settingModel.field dataUsingEncoding:NSASCIIStringEncoding];
        NSData *contentData = [settingModel.content dataUsingEncoding:NSUTF8StringEncoding];
        [sendData appendData:keyData];
        [sendData appendData:contentData];
        return sendData;
    }
    
    //------------ 报文头 -------------
    //起始地址(事务处理标识符)
    NSData *headData = [JCDataConvert intToDataOfTwoByte:settingModel.regAddr];
    [sendData appendData:headData];
    
    //协议标识符
    Byte identify[2] = {0x00,0x00};
    NSData *idData = [NSData dataWithBytes:identify length:sizeof(identify)];
    [sendData appendData:idData];
    
    //长度(从本字节下一个到最后)要根据设置的内容来调整
    NSData *head_data_leng = [JCDataConvert intToDataOfTwoByte:9];;
    [sendData appendData:head_data_leng];
    
    //设置的端点类型(EMS,Master)   设备地址
    CmdEnpointType cmdType_head = [self toCmdType:type];
    NSData *typeData = [JCDataConvert intToData:(int)cmdType_head];
    [sendData appendData:typeData];
    
    //------------------------
    //设置的端点类型(EMS,Master)   设备地址
    CmdEnpointType cmdType_mod = [self toCmdType:type];
    NSData *typeData2 = [JCDataConvert intToData:(int)cmdType_mod];
    [sendData appendData:typeData2];
    
    //指令类型(写单个保持寄存器)    功能码
    NSData *funData = [JCDataConvert intToData:0x10];
    [sendData appendData:funData];
    
    
    
    //设置值(字节根据文档查看)
    NSData *setData ;
    
    if([settingModel.type isEqualToString:@"text"]){
        setData = [settingModel.content dataUsingEncoding:NSASCIIStringEncoding];
        NSLog(@"111---->%@=== 长度:%ld",settingModel.content,settingModel.content.length);
        NSLog(@"222---->长度:%ld",settingModel.content.length);
        NSLog(@"---->转成ASCLL码:%@",setData);
//        setData  = [JCDataConvert stringToBytes:[settingModel.content stringByReplacingOccurrencesOfString:@" " withString:@""]];
    }
    if([settingModel.type isEqualToString:@"number"]){
        int data_len = settingModel.bitWidth / 16;
        if(settingModel.ratio.length>0){
            NSString *ratioStr = [NSString stringWithFormat:@"%lf",[settingModel.ratio doubleValue]];
            NSDecimalNumber *ratio = [NSDecimalNumber decimalNumberWithString:ratioStr];
            NSDecimalNumber *content  = [NSDecimalNumber decimalNumberWithString:settingModel.content];
            NSDecimalNumber *result = [content decimalNumberByDividingBy:ratio];
            if(data_len>1){
                setData = [JCDataConvert intToData:[settingModel.content integerValue] byteCount:data_len*2];
            }else{
                setData = [JCDataConvert intToDataOfTwoByte:[result integerValue]];
            }
            
            NSLog(@"---->设置有精度的数据:%@ = %ld 精度:%@",settingModel.field,[result integerValue],settingModel.ratio);
        }else{
            //这里要看数据占几个寄存器,数据的字节数必须是寄存器的数量的2位(一个寄存器16位,也就是2个字节)
            
            if(data_len>1){
                setData = [JCDataConvert intToData:[settingModel.content integerValue] byteCount:data_len*2];
            }else{
                setData = [JCDataConvert intToDataOfTwoByte:[settingModel.content integerValue]];
            }
           
            NSLog(@"---->设置整数的数据:%@ = %ld",settingModel.field,[settingModel.content integerValue]);
        }
        
    }
    
    if([settingModel.type isEqualToString:@"command"]){//发一个字节
        setData = [JCDataConvert intToDataOfTwoByte:[settingModel.content integerValue]];
    }
    
    if([settingModel.type isEqualToString:@"select"]){
        setData = [JCDataConvert intToDataOfTwoByte:[settingModel.content integerValue]];
    }
    
    if([settingModel.type isEqualToString:@"switch"]){
        setData = [JCDataConvert intToDataOfTwoByte:[settingModel.content integerValue]];
    }
    //位数据
    if(settingModel.isBit){

        NSLog(@"------>要设置的值%@ = %@",settingModel.field,settingModel.content);
        NSLog(@"------>整个寄存器的值:%ld",settingModel.originalValue);
//        NSInteger value = [self modifyByteWith:settingModel.bitOriginalValue newValue:[settingModel.content integerValue] bitWidth:settingModel.bitWidth offset:settingModel.offset];
//        NSLog(@"------>要发送的值:%ld",value);
        setData = [JCDataConvert intToDataOfTwoByte:settingModel.originalValue];
        //赋值
//        settingModel.bitOriginalValue = value;
    }
    
    //如果是时间校准,写三个寄存器  6个字节
    if([settingModel.type isEqualToString:@"date"]&&[settingModel.field isEqualToString:@"Pck_ctrlTimyear"]){
        if(settingModel.content.length>0){
            NSString *seperatorKey = @"-";
            if([settingModel.content containsString:@"/"]){
                seperatorKey = @"/";
            }
            NSString *yearStr = [[settingModel.content componentsSeparatedByString:@" "]firstObject];
            NSString *timeStr = [[settingModel.content componentsSeparatedByString:@" "]lastObject];
            NSArray *yearArr  = [yearStr componentsSeparatedByString:seperatorKey];
            NSArray *timeArr  = [timeStr componentsSeparatedByString:@":"];

            NSInteger year   = [[yearArr safeObjectAtIndex:0] integerValue];
            NSInteger month  = [[yearArr safeObjectAtIndex:1] integerValue];
            NSInteger day    = [[yearArr safeObjectAtIndex:2] integerValue];
            NSInteger hour   = [[timeArr safeObjectAtIndex:0] integerValue];
            NSInteger minute = [[timeArr safeObjectAtIndex:1] integerValue];
            NSInteger second = [[timeArr safeObjectAtIndex:2] integerValue];
            //由于关系到时区问题,这里不使用data.year
            Byte dateByte[6] = {year%1000,month,day,hour,minute,second};
            setData = [NSData dataWithBytes:dateByte length:sizeof(dateByte)];
        }
        
    }
    
    
    //起始地址
    NSData *addressData = [JCDataConvert intToDataOfTwoByte:settingModel.regAddr];
    [sendData appendData:addressData];
    
    //写寄存器的个数(2个字节)
     int byteRegLeng = settingModel.bitWidth / 16;
    
    //如果是时间校准,写三个寄存器
    if([settingModel.type isEqualToString:@"date"]&&[settingModel.field isEqualToString:@"Pck_ctrlTimyear"]){
        byteRegLeng = 3;
    }
    NSData *regLengData = [JCDataConvert intToDataOfTwoByte:byteRegLeng?byteRegLeng:1];
    
   
    [sendData appendData:regLengData];
    
    //写寄存器的数据长度  ASCLL字符串要根据数据长度算出占多少寄存器,不足的补0  整形的不用
    int data_leng = setData.length;
    NSData *lengData = [JCDataConvert intToData:setData.length];
    if([settingModel.type isEqualToString:@"text"]){
        data_leng = byteRegLeng * 2;
        lengData = [JCDataConvert intToData:data_leng];
        [sendData appendData:lengData];
    }else{
        [sendData appendData:lengData];
    }
   
    
    
    //设置值  (如果是ASCLL,要补0) 整形不用
    if([settingModel.type isEqualToString:@"text"]){
        setData = [self fillZeroByteWithData:setData leng:data_leng];
        [sendData appendData:setData];
    }else{
        [sendData appendData:setData];
    }
    
    
    
    //头部里的长度要根据设置的内容修改一下() 类型 + 类型 + 功能码 + 地址 + 寄存器个数 +数据长度 + 校验码
    int totalLeng = typeData.length + typeData2.length + funData.length + addressData.length + regLengData.length + lengData.length + setData.length + 2;
    Byte head_leng[2] = {(totalLeng & 0xFF)<<8,totalLeng & 0xFF};
    [sendData replaceBytesInRange:NSMakeRange(4, 2) withBytes:head_leng];
    
    
    //校验码
    Byte  data_bytes[sendData.length];
    [sendData getBytes:data_bytes length:sendData.length];
    
    int crc_code = [self CRC_16_MODBUS:data_bytes leng:sendData.length];
    NSData *crcData = [JCDataConvert intToDataOfTwoByte:crc_code];
    [sendData appendData:crcData];
    return sendData;
}


+(NSData*)fillZeroByteWithData:(NSData*)data leng:(int)leng
{
    NSMutableData *mtbData = [NSMutableData dataWithData:data];
    for (int i = 0; i < leng - data.length; i++) {
        Byte byte[] = {0x00};
        NSData *data = [NSData dataWithBytes:byte length:sizeof(byte)];
        [mtbData appendData:data];
    }
    return mtbData.copy;
}


+(CmdEnpointType)toCmdType:(LocalSettingType)settingType
{
    switch (settingType) {
        case LocalSettingType_EMS:
            return CmdEnpointTypeEMS;
            break;
        case LocalSettingType_Master:
            return CmdEnpointTypeMaster;
            break;
        case LocalSettingType_Pack1:
            return CmdEnpointTypePack1;
            break;
        case LocalSettingType_Pack2:
            return CmdEnpointTypePack2;
            break;
        case LocalSettingType_Pack3:
            return CmdEnpointTypePack3;
            break;
        case LocalSettingType_Pack4:
            return CmdEnpointTypePack4;
            break;
        case LocalSettingType_Pack5:
            return CmdEnpointTypePack5;
            break;
        case LocalSettingType_Pack6:
            return CmdEnpointTypePack6;
            break;
        case LocalSettingType_Pack7:
            return CmdEnpointTypePack7;
            break;
        case LocalSettingType_Pack8:
            return CmdEnpointTypePack8;
            break;
        case LocalSettingType_EMU:
            return CmdEnpointTypeEMU;
            break;
            
        default:
            [QMUITips showError:@"未知指令类型".rh_localized];
            return CmdEnpointTypeUnkown;
            break;
    }
}

+(LocalSettingType)toSettingType:(CmdEnpointType)settingType
{
    switch (settingType) {
        case CmdEnpointTypeEMS:
            return LocalSettingType_EMS;
            break;
        case CmdEnpointTypeMaster:
            return LocalSettingType_Master;
            break;
        case CmdEnpointTypePack1:
            return LocalSettingType_Pack1;
            break;
        case CmdEnpointTypePack2:
            return LocalSettingType_Pack2;
            break;
        case CmdEnpointTypePack3:
            return LocalSettingType_Pack3;
            break;
        case CmdEnpointTypePack4:
            return LocalSettingType_Pack4;
            break;
        case CmdEnpointTypePack5:
            return LocalSettingType_Pack5;
            break;
        case CmdEnpointTypePack6:
            return LocalSettingType_Pack6;
        case CmdEnpointTypeEMU:
            return LocalSettingType_EMU;
            
            break;
        default:
            return LocalSettingType_EMS;
            break;
    }
}


/// 修改字节中的某几位
/// - Parameters:
///   - value: 原来的值
///   - newValue: 要修改的值
///   - bitWidth: 位宽(要修改的位数)
///   - offset: 从哪一位开始修改
+(NSInteger)modifyByteWith:(uint16_t)value newValue:(int)newValue bitWidth:(int)bitWidth offset:(int)offset {
    
    int mask = [self offsetValueWithBitWidth:bitWidth];
    
    // 清除目标位
    value &= ~(mask << offset); // 11111000
    
    // 将新值移到正确的位置
    newValue <<= offset; // 00001000
    
    // 将新值插入到字节中
    NSInteger finalValue =    value |= newValue; // 10101000
    
    /*----方法一
         unsigned char byte = 0x55; // 10101010
         unsigned char new_value = 2; // 0000010
      
         // 清除目标位
         byte &= ~(0x3 << 2); // 11111000
      
         // 将新值移到正确的位置
         new_value <<= 2; // 00001000
      
         // 将新值插入到字节中
         byte |= new_value; // 10101000
      
         printf("Modified byte: %x\n", byte);
      
         return 0;

     */
    
    
    /*-----方法二
        unsigned char byte = 0x55; // 10101010
        unsigned char new_value = 2; // 0000010
        int mask = 0x3; // 00000011
        int shift = 2; // 目标位数
     
        byte = (byte & ~(mask << shift)) | (new_value << shift);
     
        printf("Modified byte: %x\n", byte);
 */
    return finalValue;
}


// CRC 高位字节值表 */
const uint8_t CRCByteHi[] = {
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40};
// CRC低位字节值表*/
const uint8_t CRCByteLo[] = {
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
    0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
    0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
    0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
    0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
    0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
    0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
    0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
    0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
    0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
    0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
    0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
    0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
    0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
    0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
    0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
    0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
    0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
    0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
    0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
    0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
    0x43, 0x83, 0x41, 0x81, 0x80, 0x40};

+(uint16_t)CRC_16_MODBUS:(uint8_t*)puchMsg leng:(uint16_t) usDataLen;
{
    uint8_t uCRCByteHi = 0xFF; // 高CRC字节初始化
    uint8_t uCRCByteLo = 0xFF; // 低CRC 字节初始化
    uint8_t uIndex;            // CRC循环中的索引
    while (usDataLen--)
    {                                       // 传输消息缓冲区
        uIndex = uCRCByteHi ^ (*puchMsg++); // 计算CRC
        uCRCByteHi = uCRCByteLo ^ CRCByteHi[uIndex];
        uCRCByteLo = CRCByteLo[uIndex];
    }
    return (((uint16_t)uCRCByteHi << 8) | uCRCByteLo);
}


+(int)offsetValueWithBitWidth:(int)bitWith
{
    int offsetValue = 0;
    switch (bitWith) {
        case 1:
            offsetValue = 1;
            break;
        case 2:
            offsetValue = 3;
            break;
        case 3:
            offsetValue = 7;
            break;
        case 4:
            offsetValue = 15;
            break;
        case 5:
            offsetValue = 31;
            break;
        case 6:
            offsetValue = 63;
            break;
        case 7:
            offsetValue = 127;
            break;
        case 8:
            offsetValue = 255;
            break;
        case 9:
            offsetValue = 511;
            break;
        case 10:
            offsetValue = 1023;
            break;
        case 11:
            offsetValue = 2047;
            break;
        case 12:
            offsetValue = 4095;
            break;
        case 13:
            offsetValue = 8191;
            break;
        case 14:
            offsetValue = 16383;
            break;
        case 15:
            offsetValue = 32767;
            break;
        case 16:
            offsetValue = 65535;
            break;
        default:
            return offsetValue;
            break;
    }
    return offsetValue;
}
@end
